#define _POSIX_SOURCE
#define _BSD_SOURCE

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include "rngs.h"

#ifndef MAX_PLAYER
#define MAX_PLAYER 4
#endif

#ifndef MAX_SUPP
#define MAX_SUPP 13
#endif

#ifndef TOTAL_VP_CARD
#define TOTAL_VP_CARD 6
#endif

int checkScoreFor(int expected, int player, struct gameState *post)
{
	int result;

	result = scoreFor(player, post);
	//printf("result = %4d\n", result);
	assert(result == expected);

	return 0;
}

void sigabrt_catch(int sig)
{
	printf("SIGABRT has been caught\n");
	exit(0);
}

int main(int argc, char **argv)
{
	int i, n, r, expected, fullDeckCount;
	int curse_count, estate_count, duchy_count, province_count, great_hall_count, gardens_count; 

	struct gameState G;

	signal(SIGABRT, sigabrt_catch);

	printf("Testing scoreFor.\n");

	printf("RANDOM TESTS.\n");

	/* Set Random Number Generator */
	SelectStream(1);
	PutSeed(1);

	for (n = 1; n <= 20000; n++) {
		for (i = 0; i < sizeof(struct gameState); i++) {
			((char *) &G)[i] = floor(Random() * 256);
		}

		/* Randomly Set Game Numbers */ 
		G.whoseTurn = floor(Random() * MAX_PLAYER);;
		G.deckCount[G.whoseTurn] = floor(Random() * MAX_DECK);
		G.discardCount[G.whoseTurn] = floor(Random() * MAX_DECK);
		G.handCount[G.whoseTurn] = floor(Random() * MAX_HAND);
		
		curse_count = 0;
		estate_count = 0;
		duchy_count = 0;
		province_count = 0; 
		great_hall_count = 0;
		gardens_count = 0; 

		/* Fill deck with VP cards */
		for (i = 0; i < G.deckCount[G.whoseTurn]; i++) {
			r = floor(Random() * TOTAL_VP_CARD);

			switch (r) {
			
			case 0:
				G.deck[G.whoseTurn][i] = curse;
				curse_count++;
				break;

			case 1:
				G.deck[G.whoseTurn][i] = estate;
				estate_count++;
				break;

			case 2:
				G.deck[G.whoseTurn][i] = duchy;
				duchy_count++;
				break;

			case 3:
				G.deck[G.whoseTurn][i] = province;
				province_count++;
				break;

			case 4:
				G.deck[G.whoseTurn][i] = great_hall;
				great_hall_count++;
				break;

			default:
				G.deck[G.whoseTurn][i] = gardens;
				gardens_count++;
				break;
			}
		}

		/* Fill discard with VP cards */
		for (i = 0; i < G.discardCount[G.whoseTurn]; i++) {
			r = floor(Random() * TOTAL_VP_CARD);

			switch (r) {
			
			case 0:
				G.discard[G.whoseTurn][i] = curse;
				curse_count++;
				break;

			case 1:
				G.discard[G.whoseTurn][i] = estate;
				estate_count++;
				break;

			case 2:
				G.discard[G.whoseTurn][i] = duchy;
				duchy_count++;
				break;

			case 3:
				G.discard[G.whoseTurn][i] = province;
				province_count++;
				break;

			case 4:
				G.discard[G.whoseTurn][i] = great_hall;
				great_hall_count++;
				break;

			default:
				G.discard[G.whoseTurn][i] = gardens;
				gardens_count++;
				break;
			}
		}

		/* Fill hand with VP cards */
		for (i = 0; i < G.handCount[G.whoseTurn]; i++) {
			r = floor(Random() * TOTAL_VP_CARD);

			switch (r) {
			
			case 0:
				G.hand[G.whoseTurn][i] = curse;
				curse_count++;
				break;

			case 1:
				G.hand[G.whoseTurn][i] = estate;
				estate_count++;
				break;

			case 2:
				G.hand[G.whoseTurn][i] = duchy;
				duchy_count++;
				break;

			case 3:
				G.hand[G.whoseTurn][i] = province;
				province_count++;
				break;

			case 4:
				G.hand[G.whoseTurn][i] = great_hall;
				great_hall_count++;
				break;

			default:
				G.hand[G.whoseTurn][i] = gardens;
				gardens_count++;
				break;
			}
		}

		fullDeckCount = G.deckCount[G.whoseTurn] + G.discardCount[G.whoseTurn] + G.handCount[G.whoseTurn];
		expected = ((curse_count * -1) + (estate_count * 1) + (duchy_count * 3) + (province_count * 6) +
				(great_hall * 1) + (gardens * (fullDeckCount / 10)));

		if (argc > 1 && strcmp(argv[1], "-v") == 0) {
			printf("Test #%5d: player = %d cur = %3d est = %3d duc = %3d pv = %3d gh = %3d gd = %3d expected = %4d\n", 
					n, G.whoseTurn, curse_count, estate_count, duchy_count, province_count, great_hall_count, gardens_count, expected);
		}
		
		checkScoreFor(expected, G.whoseTurn, &G);
	}

	printf ("ALL TESTS OK\n");

	return 0;
}